<template>
	<Drag class="drag-ball">
		<div v-if="!token">
			登录失败 😱
			<br />
			正在尝试重新登录...
		</div>
		<div v-else-if="token && !cameraStream && !screenStream">
			登录成功！🥰
			<br />
			正在请求授权...
		</div>
		<div v-else>
			<div class="relative">
				<Timer :duration="1000"> 授权成功！🎉 </Timer>
				<Timer :duration="1000" :after="true"> 录像中... 🧐 </Timer>
				<div class="flex flex-col items-center justify-end">
					<button
						@click="toggleZoom"
						class="bg-opacity-70 border-none rounded cursor-pointer hover:shadow-lg transition-shadow p-2"
					>
						<div v-if="isZoomed" class="text-3xl">-</div>
						<div v-else class="text-3xl">+</div>
					</button>
				</div>
			</div>
			<div v-show="isZoomed" class="space-y-1">
				<video ref="cameraRef" v-show="cameraStream" class="w-64 h-48" autoplay muted></video>
				<div class="relative flex py-5 items-center">
					<div class="flex-grow border-t border-gray-400"></div>
					<span class="flex-shrink mx-4 text-gray-400"> 摄像👆 😎 👇 屏幕</span>
					<div class="flex-grow border-t border-gray-400"></div>
				</div>
				<video ref="screenRef" v-show="screenStream" class="w-64 h-48" autoplay muted></video>
			</div>
			<button
				@click="captureAndUploadImages()"
				class="bg-opacity-70 border-none rounded cursor-pointer hover:shadow-lg transition-shadow p-2"
			>
				截图
			</button>
			<div class="w-64 h-30 overflow-y-auto">
				<h3>已打开的标签页数量: {{ tabs.length }}</h3>
			</div>
		</div>
	</Drag>
</template>

<script lang="ts" setup>
	import { ref, onMounted, onUnmounted, nextTick } from 'vue'
	import Drag from '@/compoents/Drag.vue'
	import Timer from '@/compoents/Timer.vue'
	import '@/style/style.scss'
	import { jwtDecode } from 'jwt-decode'
	import { _getUserInfo } from '@/api/user'

	import { OssUtils } from '@/utils/ossUtils'

	import { Room, RoomEvent } from 'livekit-client'
	import { _getJoinToken } from '@/api/livekit'

	const token = ref<string | null>(localStorage.getItem('token'))
	const retryInterval = 5000
	let retryTimer: any
	const cameraRef = ref<HTMLVideoElement | null>(null)
	const screenRef = ref<HTMLVideoElement | null>(null)
	const cameraStream = ref<MediaStream | null>(null)
	const screenStream = ref<MediaStream | null>(null)
	const isZoomed = ref(true)
	const tabs = ref<string[]>([]) // 用于存储打开的标签页

	const UID = ref<string | null>(null)

	const livekitURL = 'wss://ahutoj-uo7196ti.livekit.cloud'
	let livekitToken: string = ''
	const room = new Room()

	onMounted(() => {
		if (!token) {
			startRetry()
		} else if (!isValidToken(token.value!)) {
			token.value = null
			alert('Token 格式错误，请清理登录信息！')
		} else {
			_getUserInfo({})
				.then((res: any) => {
					UID.value = res.UID
				})
				.catch((error) => {
					console.error('Error getting user info:', error)
				})
				.then(() => {
					Promise.all([requestRecording(), requestScreenShare()])
						.then(() => {
							console.log('All permissions granted.')
						})
						.then(() => {
							connectLiveKit()
						})
						.catch((error) => {
							console.error('Error connecting to LiveKit:', error)
						})
				})
				.catch((error) => {
					console.error('Error requesting permissions:', error)
				})
		}
		// @ts-ignore
		chrome.runtime.sendMessage({ action: 'getAllTabs' }, (response) => {
			if (response && response.tabs) {
				tabs.value = response.tabs
			} else {
				console.error('无法获取标签页信息。')
			}
		})
		// @ts-ignore
		chrome.runtime.onMessage.addListener((response) => {
			if (response.action === 'updateTabs') {
				tabs.value = response.tabs
				console.log('标签页信息更新成功。')
			}
		})
	})

	onUnmounted(() => {
		clearInterval(retryTimer)
		if (cameraStream.value) {
			cameraStream.value.getTracks().forEach((track) => track.stop())
		}
		if (screenStream.value) {
			screenStream.value.getTracks().forEach((track) => track.stop())
		}
	})

	function startRetry() {
		retryTimer = setInterval(() => {
			if (token.value) {
				clearInterval(retryTimer)
			} else {
				console.log('Retrying login...')
				token.value = localStorage.getItem('token')
				if (token && !isValidToken(token.value!)) {
					token.value = null
					alert('Token 格式错误，请清理登录信息！')
				}
			}
		}, retryInterval)
	}

	function isValidToken(token: string): boolean {
		try {
			jwtDecode(token)
			return true
		} catch (error) {
			return false
		}
	}

	async function requestRecording() {
		try {
			cameraStream.value = await navigator.mediaDevices.getUserMedia({
				video: true,
				audio: false,
			})
			await nextTick()
			if (cameraRef.value && cameraStream.value) {
				cameraRef.value.srcObject = cameraStream.value
				console.log('Video stream started successfully.')
			}
		} catch (error) {
			console.error('Error requesting Recording:', error)
		}
	}

	async function requestScreenShare() {
		try {
			screenStream.value = await navigator.mediaDevices.getDisplayMedia({
				video: true,
				audio: false,
			})
			await nextTick()
			if (screenRef.value && screenStream.value) {
				screenRef.value.srcObject = screenStream.value
				console.log('Screen sharing started successfully.')
			}
		} catch (error) {
			console.error('Error requesting screen share permissions:', error)
		}
	}

	function toggleZoom() {
		isZoomed.value = !isZoomed.value
	}

	async function captureAndUploadImages() {
		const canvas = document.createElement('canvas')
		const context = canvas.getContext('2d')
		if (cameraRef.value && cameraStream.value) {
			canvas.width = cameraRef.value.videoWidth
			canvas.height = cameraRef.value.videoHeight
			context?.drawImage(cameraRef.value, 0, 0, canvas.width, canvas.height)
			canvas.toBlob((blob) => {
				OssUtils.uploadCameraImage(blob!, UID.value!)
			})
		}
		if (screenRef.value && screenStream.value) {
			canvas.width = screenRef.value.videoWidth
			canvas.height = screenRef.value.videoHeight
			context?.drawImage(screenRef.value, 0, 0, canvas.width, canvas.height)
			canvas.toBlob((blob) => {
				OssUtils.uploadScreenImage(blob!, UID.value!)
			})
		}
	}

	async function connectLiveKit() {
		await _getJoinToken({}, 'monitor').then((res: any) => {
			livekitToken = res.Token
		})
		room.on(RoomEvent.Connected, () => {
			console.log('Connected to LiveKit room', room.name)
		})
		room.on(RoomEvent.Disconnected, () => {
			console.log('Disconnected from LiveKit room')
		})
		await room.connect(livekitURL, livekitToken)
		if (cameraStream.value) {
			const tracks = cameraStream.value.getTracks()
			for (const track of tracks) {
				try {
					await room.localParticipant.publishTrack(track)
				} catch (error) {
					console.error('Failed to publish camera track', track.kind, error)
				}
			}
		}

		if (screenStream.value) {
			const tracks = screenStream.value.getTracks()
			for (const track of tracks) {
				try {
					await room.localParticipant.publishTrack(track)
				} catch (error) {
					console.error('Failed to publish screen track', track.kind, error)
				}
			}
		}
	}
</script>

<style scoped></style>
